import frameworkManager from "./frameworkManager";
import EngineUtil from "./EngineUtil";

const pool = {};
const prefabList = {};

 class NodePool {
    static _instance:NodePool;
    static get Instance():NodePool {
        if (!NodePool._instance) {
            NodePool._instance = new NodePool();
        }
        return NodePool._instance;
    }

    public _pathList;
    addPath(paths) {
        this._pathList = this._pathList || {};
        if (!Array.isArray(paths)) {
            paths = [paths];
        }
        for (let i = 0; i < paths.length; i++) {
            let basename = cc.path.basename(paths[i]);
            this._pathList[basename] = this._pathList[basename] || paths[i];
        }
        console.log(this._pathList);
    };

    loadPool(prefabs, callback) {
        if (!Array.isArray(prefabs)) {
            prefabs = [prefabs];
        }
        const paths = prefabs.map(prefab => this._pathList[prefab]);
        cc.resources.load(paths, cc.Prefab, (err, assets) => {
            if (err) {
                console.error(err);
                return;
            }
            if (!Array.isArray(assets)) {
                assets = [assets];
            }
            for (let i = 0; i < assets.length; i++) {
                let prefab = assets[i];
                let name = prefab.name;
                if (!this.hasPool(name)) {
                    if (pool[name]) {
                        for (let j = 0; j < pool[name].length; j++) {
                            let node = pool[name][j];
                            EngineUtil.destroyNode(node);
                        }
                    }
                    pool[name] = [];
                    prefabList[name] = prefab;
                    for (let k = 0; k < 1; k++) {
                        let instance = cc.instantiate(prefab);
                        instance.active = false;
                        pool[name].push(instance);
                    }
                }
            }
            if (callback) {
                callback();
            }
        });
    };

    initPool(prefabName, count = 1, poolName = "") {
        if (!poolName) {
            poolName = prefabName;
        }
        if (!this.hasPool(poolName)) {
            if (pool[poolName]) {
                for (let i = 0; i < pool[poolName].length; i++) {
                    let node = pool[poolName][i];
                    EngineUtil.destroyNode(node);
                }
            }
            pool[poolName] = [];
            prefabList[poolName] = prefabName;
            for (let j = 0; j < count; j++) {
                let instance = cc.instantiate(prefabName);
                instance.active = false;
                pool[poolName].push(instance);
            }
        }
    };

    hasPool(poolName) {
        return prefabList[poolName] && prefabList[poolName].isValid;
    };

    putNode(poolName, node) {
        if (cc.isValid(node)) {
            let poolArray = pool[poolName];
            if (poolArray) {
                if (poolArray.findIndex(item => item === node) >= 0) {
                    console.error("putNode error", poolName);
                    frameworkManager.error("putNode error");
                } else {
                    node.stopAllActions();
                    node.removeFromParent(true);
                    node.x = 0;
                    node.y = 0;
                    node.scale = 1;
                    node.opacity = 255;
                    node.active = false;
                    poolArray.push(node);
                }
            } else {
                console.error("putNode: pool %s not found", poolName);
            }
        } else {
            console.error("putNode: node param is invalid");
        }
    };

    getNode(poolName) {
        let poolArray = pool[poolName];
        if (!poolArray) {
            console.error("getNode: pool %s not found", poolName);
            return null;
        }
        let node = poolArray.length > 0 ? poolArray.pop() : cc.instantiate(prefabList[poolName]);
        node = cc.isValid(node) ? node : cc.instantiate(prefabList[poolName]);
        node.active = true;
        node.x = 0;
        node.y = 0;
        return node;
    };

    reset() {
        if (pool) {
            for (let poolName in pool) {
                let poolArray = pool[poolName];
                while (poolArray.length > 0) {
                    EngineUtil.destroyNode(poolArray.pop());
                }
            }
        }
    };

    getPool() {
        return pool;
    };

    _test() {
        console.log(pool);
    };
}

export default NodePool.Instance;
